/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.dusa.worklog.viewer;

import cz.dusa.worklog.controller.WorklogDataException;
import cz.dusa.worklog.controller.WorklogDataListener;
import cz.dusa.worklog.controller.WorklogDataManager;
import cz.dusa.worklog.datalib.Customer;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.awt.UndoRedo;
import org.openide.cookies.SaveCookie;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;

/**
 * Top component which displays something.
 */
@ConvertAsProperties(dtd = "-//cz.dusa.worklog.viewer//CustomerEditor//EN",
autostore = false)
//public final class CustomerEditorTopComponent extends TopComponent implements LookupListener {
public final class CustomerEditorTopComponent extends TopComponent implements WorklogDataListener<Customer> {

    private static CustomerEditorTopComponent instance;
    /** path to the icon used by the component and its open action */
    static final String ICON_PATH = "cz/dusa/worklog/viewer/Contact.png";
    private static final String PREFERRED_ID = "CustomerEditorTopComponent";
    private Lookup.Result result = null;
    private UndoRedo.Manager manager = new UndoRedo.Manager();
    private final SaveCookieImpl impl;
    private final InstanceContent content;
    private Customer customer = null;

    @Deprecated
    public CustomerEditorTopComponent() {
        throw new UnsupportedOperationException("Do not use default constructor of CustomerEditorTopComponent. You can use CustomerEditorTopComponent(Customer)");
    }

    private CustomerEditorTopComponent(Customer customer) {
        initComponents();

        setToolTipText(NbBundle.getMessage(CustomerEditorTopComponent.class, "HINT_CustomerEditorTopComponent"));
        setIcon(ImageUtilities.loadImage(ICON_PATH, true));

        JTextField[] textfields = new JTextField[]{name, street, city, zip, country, phone, fax, mobile};
        for (JTextField textfield : textfields) {
            textfield.getDocument().addUndoableEditListener(manager);
            textfield.getDocument().addDocumentListener(new DocumentListener() {

                public void insertUpdate(DocumentEvent arg0) {
                    fire(true);
                }

                public void removeUpdate(DocumentEvent arg0) {
                    fire(true);
                }

                public void changedUpdate(DocumentEvent arg0) {
                    fire(true);
                }
            });
        }
        //Create a new instance of our SaveCookie implementation:
        impl = new SaveCookieImpl();

        //Create a new instance of our dynamic object:
        content = new InstanceContent();

        //Add the dynamic object to the TopComponent Lookup:
        associateLookup(new AbstractLookup(content));

        setCustomer(customer);
    }

    public void fire(boolean modified) {
        if (modified) {
            //If the text is modified,
            //we add SaveCookie impl to Lookup:
            content.add(impl);
        } else {
            //Otherwise, we remove the SaveCookie impl from the lookup:
            content.remove(impl);
        }
    }

    /**
     * @return the customer
     */
    public Customer getCustomer() {
        return customer;
    }

    /**
     * @param customer the customer to set
     */
    public void setCustomer(Customer customer) {
        if (getCustomer() != null) {
            WorklogDataManager.getInstance().removeWorklogDataListener(this, Customer.class, getCustomer().getId());
        }

        this.customer = customer;

        name.setText(getCustomer().getName());
        street.setText(getCustomer().getStreet());
        city.setText(getCustomer().getCity());
        zip.setText(getCustomer().getZip());
        country.setText(getCustomer().getCountry());
        phone.setText(getCustomer().getPhone());
        fax.setText(getCustomer().getFax());
        mobile.setText(getCustomer().getMobile());
        manager.discardAllEdits();
        fire(false);

        if (customer.getName() != null && !customer.getName().equals("")) {
            setName(customer.getName());
        } else {
            setName(NbBundle.getMessage(CustomerEditorTopComponent.class, "Customer"));
        }

        manager.discardAllEdits();
        WorklogDataManager.getInstance().addWorklogDataListener(this, Customer.class, customer.getId());
    }

    public void afterCreate(Customer customer) {
        //do nothing
    }

    public void afterUpdate(Customer customer) {
        setCustomer(customer);
    }

    public void beforeDelete(Customer customer) {
        close();
    }

//    public void resultChanged(LookupEvent ev) {
//        throw new UnsupportedOperationException("Not supported yet.");
//    }
    private class SaveCookieImpl implements SaveCookie {

        @Override
        public void save() throws IOException {
            fire(false);
            getCustomer().setName(name.getText());
            getCustomer().setStreet(street.getText());
            getCustomer().setCity(city.getText());
            getCustomer().setZip(zip.getText());
            getCustomer().setCountry(country.getText());
            getCustomer().setPhone(phone.getText());
            getCustomer().setFax(fax.getText());
            getCustomer().setMobile(mobile.getText());
            try {
                if (getCustomer().getId() != null) {
                    //this window listens to CustomerDataManager on current customer => it will be refreshed afterUpdate(Customer)
                    WorklogDataManager.getInstance().merge(getCustomer());
                } else {
                    //
                    afterUpdate((Customer) WorklogDataManager.getInstance().persist(getCustomer()));
                }
            } catch (WorklogDataException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        name = new javax.swing.JTextField();
        street = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        city = new javax.swing.JTextField();
        zip = new javax.swing.JTextField();
        country = new javax.swing.JTextField();
        phone = new javax.swing.JTextField();
        fax = new javax.swing.JTextField();
        mobile = new javax.swing.JTextField();

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.jPanel1.border.title"))); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.jLabel1.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.jLabel2.text")); // NOI18N

        name.setText(org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.name.text")); // NOI18N

        street.setText(org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.street.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.jLabel3.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.jLabel4.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.jLabel5.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.jLabel6.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel7, org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.jLabel7.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel8, org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.jLabel8.text")); // NOI18N

        city.setText(org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.city.text")); // NOI18N

        zip.setText(org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.zip.text")); // NOI18N

        country.setText(org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.country.text")); // NOI18N

        phone.setText(org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.phone.text")); // NOI18N

        fax.setText(org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.fax.text")); // NOI18N

        mobile.setText(org.openide.util.NbBundle.getMessage(CustomerEditorTopComponent.class, "CustomerEditorTopComponent.mobile.text")); // NOI18N

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel5)
                    .addComponent(jLabel6)
                    .addComponent(jLabel4)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2)
                    .addComponent(jLabel3)
                    .addComponent(jLabel7)
                    .addComponent(jLabel8))
                .addGap(18, 18, 18)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(mobile, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE)
                    .addComponent(fax, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE)
                    .addComponent(street, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE)
                    .addComponent(name, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE)
                    .addComponent(city, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE)
                    .addComponent(zip, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE)
                    .addComponent(phone, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE)
                    .addComponent(country, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(name, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(street, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(city, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(zip, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel5)
                    .addComponent(country, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel6)
                    .addComponent(phone, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(fax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel8)
                    .addComponent(mobile, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(46, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField city;
    private javax.swing.JTextField country;
    private javax.swing.JTextField fax;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JTextField mobile;
    private javax.swing.JTextField name;
    private javax.swing.JTextField phone;
    private javax.swing.JTextField street;
    private javax.swing.JTextField zip;
    // End of variables declaration//GEN-END:variables

    /**
     * Gets default instance. Do not use directly: reserved for *.settings files only,
     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
     * To obtain the singleton instance, use {@link #findInstance}.
     */
    public static synchronized CustomerEditorTopComponent getDefault() {
        if (instance == null) {
            instance = new CustomerEditorTopComponent();
        }
        return instance;
    }

    /**
     * Obtain the CustomerEditorTopComponent instance. Never call {@link #getDefault} directly!
     */
    public static synchronized CustomerEditorTopComponent findInstance(Customer c) {
        String preferredID = PREFERRED_ID + c.getId();

        //here was important to set the PersistenceType to PERSISTENCE_NEVER
        // (PERSISTENCE_ONLY_OPENED does not make sence because the Translator comes as an EJB and must
        //be persisted there (not localy by the window manager)

        TopComponent win = WindowManager.getDefault().findTopComponent(preferredID);
        /*
         * there is a problem that after persist of the customer the customers id is changed from null to some value
         * but the TopComponents in the WindowManager are not updated. So if I need to create another new customer
         * this window will be opened even if the customer in this window is no more with id=null. Therefore there is
         * a c.getId()==null in follwing if. But it still doesn't work correctly. Try to create a new customer, then save
         * it and doubleclick on the newly created node in the tree - another window with the customer will be opened.
         */
        if (win != null && c.getId() == null) {
            win.close();
            win = null;
        }

        if (win == null) {
            Logger.getLogger(CustomerEditorTopComponent.class.getName()).log(
                    Level.WARNING, "Cannot find {0} component. It will not be located properly in the window system.", preferredID);
            return new CustomerEditorTopComponent(c);
        }
        if (win instanceof CustomerEditorTopComponent) {
            return (CustomerEditorTopComponent) win;
        }

        Logger.getLogger(CustomerEditorTopComponent.class.getName()).log(
                Level.WARNING, "There seem to be multiple components with the ''{0}'' ID. That is a potential source of errors and unexpected behavior.", preferredID);
        return null;
    }

    @Override
    public int getPersistenceType() {
        return TopComponent.PERSISTENCE_NEVER;
    }

    @Override
    public void componentOpened() {
//        result = WindowManager.getDefault().findTopComponent("CustomersTopComponent").getLookup().lookupResult(Customer.class);
//        result.addLookupListener(this);
//        resultChanged(new LookupEvent(result));
    }

    @Override
    public void componentClosed() {
//        result.removeLookupListener(this);
//        result = null;
    }

    void writeProperties(java.util.Properties p) {
        // better to version settings since initial version as advocated at
        // http://wiki.apidesign.org/wiki/PropertyFiles
        p.setProperty("version", "1.0");
        // TODO store your settings
    }

    Object readProperties(java.util.Properties p) {
        if (instance == null) {
            instance = this;
        }
        instance.readPropertiesImpl(p);
        return instance;
    }

    private void readPropertiesImpl(java.util.Properties p) {
        String version = p.getProperty("version");
    }

    @Override
    protected String preferredID() {
        if (getCustomer() != null) {
            return PREFERRED_ID + getCustomer().getId();
        } else {
            return PREFERRED_ID;
        }
    }

    @Override
    public UndoRedo getUndoRedo() {
        return manager;
    }

    private void saveCurrentCustomer() {
        if (getLookup().lookup(SaveCookieImpl.class) != null) {
            try {
                impl.save();
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }

    @Override
    public boolean canClose() {
        saveCurrentCustomer();
        return true;
    }
}
